package com.bjpowernode.boss.web.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bjpowernode.boss.common.cilent.RedisClient;
import com.bjpowernode.boss.common.constants.KeyConstants;
import com.bjpowernode.boss.common.enums.AjaxCode;
import com.bjpowernode.boss.common.enums.Status;
import com.bjpowernode.boss.common.error.BossException;
import com.bjpowernode.boss.common.utils.NoUtil;
import com.bjpowernode.boss.convert.UserInfoConvert;
import com.bjpowernode.boss.db.domain.UserAccount;
import com.bjpowernode.boss.db.domain.UserInfo;
import com.bjpowernode.boss.db.mapper.UserAccountMapper;
import com.bjpowernode.boss.db.mapper.UserInfoMapper;
import com.bjpowernode.boss.web.service.UserInfoService;
import com.bjpowernode.boss.web.models.vo.UserInfoVo;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 *
 * @author shenlang
 * @date 2024-06-01 19:58
 * @version 1.0.0
 * TODO 添加描述
 */

@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Resource
    private RedisClient redisClient;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private UserInfoConvert userInfoConvert;
    @Autowired
    private UserAccountMapper userAccountMapper;

    @Override
    public IPage<UserInfo> getPageInfo(Integer pageNumber, Integer pageSize) {
        QueryWrapper<UserInfo> wrapper= new QueryWrapper<>();
        wrapper.orderByDesc("create_time");
        return userInfoMapper.selectPage(Page.of(pageNumber,pageSize),wrapper);
    }
    @Override
    public Map<String, Object> getPageMap(Integer page, Integer pageSize) {
        page=(page==null||page<1)?1:page;
        int frontIndex = page*pageSize-pageSize+1;
        List<UserInfoVo> userInfoVos;
        try {
            userInfoVos = redisClient.get(KeyConstants.USER_INFO, UserInfoVo.class);
            if(userInfoVos.isEmpty()){
                synchronized (this) {
                    userInfoVos = redisClient.get(KeyConstants.USER_INFO, UserInfoVo.class);
                    if(userInfoVos.isEmpty()){
                        List<UserInfo> userInfos = userInfoMapper.selectAll();
                        userInfoVos = userInfoConvert.userInfoVos(userInfos);
                        if(!userInfoVos.isEmpty()) {
                            redisClient.set(KeyConstants.USER_INFO, userInfoVos);
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            List<UserInfo> userInfos = userInfoMapper.selectAll();
            userInfoVos = userInfoConvert.userInfoVos(userInfos);
        }
        if(userInfoVos.size()<pageSize&&page>1){
            throw new BossException(AjaxCode.CURRENT_PAGE_NUMBER_IS_NOT_ERROR);
        }
        int total = userInfoVos.size()/pageSize;
        total= (userInfoVos.size()%pageSize==0)?total:total+1;
        int rearIndex = total*pageSize==userInfoVos.size()?page*pageSize:userInfoVos.size();
        Map<String,Object> map = new HashMap<>();
        map.put("page",page);
        map.put("total",total);
        map.put("data",userInfoVos.subList(frontIndex-1,rearIndex));
        return map;
    }
    @Override
    public List<UserInfo> getUserList() {
        List<UserInfo> userInfos;
        try {
            String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
            if(StrUtil.isNotBlank(userInfoJSON)){
                userInfos = JSONUtil.toList(userInfoJSON,UserInfo.class);
            }else{
                synchronized (this) {
                    userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
                    if(StrUtil.isNotBlank(userInfoJSON)){
                        userInfos = JSONUtil.toList(userInfoJSON,UserInfo.class);
                    }else{
                        userInfos = userInfoMapper.selectList(null);
                        if(!userInfos.isEmpty()){
                            redisClient.setValue(KeyConstants.USER_INFO_ALL,JSONUtil.toJsonStr(userInfos));
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            userInfos = userInfoMapper.selectList(null);
        }
        return userInfos;
    }
    @Override
    public Boolean changStatus(String id,String status) {
        String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
        if(StrUtil.isNotBlank(userInfoJSON)){
            redisClient.deleteValue(KeyConstants.USER_INFO_ALL);
        }
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("status",status).eq("id",id);
        int number = userInfoMapper.update(updateWrapper);
        return number>0;
    }
    @Override
    public boolean singleDelete(String id) {
        String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
        if(StrUtil.isNotBlank(userInfoJSON)){
            redisClient.deleteValue(KeyConstants.USER_INFO_ALL);
        }
        int number = userInfoMapper.deleteById(id);
        return number>0;
    }

    @Override
    public boolean batchDelete(List<String> ids) {
        String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
        if(StrUtil.isNotBlank(userInfoJSON)){
            redisClient.deleteValue(KeyConstants.USER_INFO_ALL);
        }
        int number = userInfoMapper.deleteBatchIds(ids);
        return number>0;
    }

    @Override
    @Transactional
    public synchronized boolean  addUserInfo(UserInfo userInfo) {
        String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
        if(StrUtil.isNotBlank(userInfoJSON)){
            List<UserInfo> list =  JSONUtil.toList(userInfoJSON,UserInfo.class);
            for (UserInfo info : list) {
                if(info.getLoginName().equals(userInfo.getLoginName())){
                    throw new BossException(AjaxCode.USER_LOGIN_NAME_DUPLICATE);
                }
            }
        }
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("login_name",userInfo.getLoginName());
        if(userInfoMapper.selectOne(queryWrapper)!=null){
            throw new BossException(AjaxCode.USER_LOGIN_NAME_DUPLICATE);
        }
        if(StrUtil.isNotBlank(userInfoJSON)){
            redisClient.deleteValue(KeyConstants.USER_INFO_ALL);
        }
        //创建用户
        return addUserAndAccount(userInfo);
    }

    @Override
    @Transactional
    public synchronized boolean editUserInfo(UserInfo userInfo) {
        if(userInfoMapper.selectById(userInfo.getId())==null){
            throw new BossException(AjaxCode.USER_NONE);
        }




        String userInfoJSON = redisClient.getValue(KeyConstants.USER_INFO_ALL);
        if(StrUtil.isNotBlank(userInfoJSON)){
            redisClient.deleteValue(KeyConstants.USER_INFO_ALL);
        }
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("login_name",userInfo.getLoginName()).set("phone",userInfo.getPhone()).set("shop_name",userInfo.getShopName()).set("shop_scope",userInfo.getShopScope()).set("user_email",userInfo.getUserEmail()).eq("id",userInfo.getId());
        int number = userInfoMapper.update(updateWrapper);
        return number>0;
    }








    private boolean addUserAndAccount(UserInfo userInfo) {
        userInfo.setId(NoUtil.getUUID());
        userInfo.setUserNo(NoUtil.getUserNo());
        userInfo.setAccountNo(NoUtil.getAccountNo());
        userInfo.setPassword(NoUtil.getUUID());
        userInfo.setPayPwd(NoUtil.getUUID());
        userInfo.setStatus(Status.DISABLE.name());
        userInfo.setCreateTime(new Date());
        userInfo.setRemark("创建商户");
        int num1 = userInfoMapper.insert(userInfo);
        //创建资金账号
        UserAccount userAccount = new UserAccount(NoUtil.getUUID(), userInfo.getUserNo(), userInfo.getAccountNo(), new BigDecimal("0"), new BigDecimal("0"), new BigDecimal("0"), Status.ENABLE.name(), "创建资金账号", new Date());
        int num2 = userAccountMapper.insert(userAccount);
        return num1 > 0 && num2 > 0;
    }
}
